import { Position, ChessUnitType, ChessUnit } from '../types/game';

// 象棋规则验证工具
export class ChessRules {
  // 检查位置是否在棋盘范围内
  static isValidPosition(pos: Position): boolean {
    return pos.x >= 0 && pos.x < 10 && pos.y >= 0 && pos.y < 9;
  }

  // 检查位置是否在己方区域（下半部分）
  static isInOwnTerritory(pos: Position): boolean {
    return pos.y >= 5; // 己方区域为棋盘下半部分
  }

  // 检查位置是否在九宫格内
  static isInPalace(pos: Position): boolean {
    return pos.x >= 3 && pos.x <= 5 && pos.y >= 7 && pos.y <= 8;
  }

  // 检查单位是否可以部署在指定位置
  static canDeployUnit(
    unitType: ChessUnitType,
    position: Position,
    existingUnits: ChessUnit[],
    boardLayout: number[][]
  ): { canDeploy: boolean; reason?: string } {
    // 基础检查：位置是否有效
    if (!this.isValidPosition(position)) {
      return { canDeploy: false, reason: '位置超出棋盘范围' };
    }

    // 检查棋盘布局是否允许部署
    if (boardLayout[position.y] && boardLayout[position.y][position.x] === 0) {
      return { canDeploy: false, reason: '此位置不可通行' };
    }

    // 检查位置是否已被占用
    const isOccupied = existingUnits.some(
      unit => unit.position.x === position.x && unit.position.y === position.y
    );
    if (isOccupied) {
      return { canDeploy: false, reason: '位置已被占用' };
    }

    // 根据单位类型检查特殊规则
    switch (unitType) {
      case 'soldier': // 锐士（兵）
        return this.validateSoldierPlacement(position);
      
      case 'cannon': // 神射（炮）
        return this.validateCannonPlacement(position, existingUnits);
      
      case 'horse': // 骠骑（马）
        return this.validateHorsePlacement(position, existingUnits);
      
      case 'chariot': // 战车（车）
        return this.validateChariotPlacement(position);
      
      case 'advisor': // 谋士（士）
        return this.validateAdvisorPlacement(position);
      
      case 'minister': // 丞相（象）
        return this.validateMinisterPlacement(position, existingUnits);
      
      case 'general': // 元帅（将）
        return this.validateGeneralPlacement(position);
      
      default:
        return { canDeploy: true };
    }
  }

  // 锐士（兵）部署规则：只能在己方区域
  private static validateSoldierPlacement(position: Position): { canDeploy: boolean; reason?: string } {
    if (!this.isInOwnTerritory(position)) {
      return { canDeploy: false, reason: '锐士只能部署在己方区域' };
    }
    return { canDeploy: true };
  }

  // 神射（炮）部署规则：需要考虑炮架位置
  private static validateCannonPlacement(
    position: Position,
    existingUnits: ChessUnit[]
  ): { canDeploy: boolean; reason?: string } {
    if (!this.isInOwnTerritory(position)) {
      return { canDeploy: false, reason: '神射只能部署在己方区域' };
    }

    // 检查是否有合适的炮架位置（前方有单位可作为炮架）
    const hasCannonMount = this.checkCannonMountAvailable(position, existingUnits);
    if (!hasCannonMount) {
      return { 
        canDeploy: true, // 允许部署，但提示效果会受限
        reason: '提示：前方无炮架，攻击效果受限' 
      };
    }

    return { canDeploy: true };
  }

  // 骠骑（马）部署规则：马走日字
  private static validateHorsePlacement(
    position: Position,
    existingUnits: ChessUnit[]
  ): { canDeploy: boolean; reason?: string } {
    if (!this.isInOwnTerritory(position)) {
      return { canDeploy: false, reason: '骠骑只能部署在己方区域' };
    }

    // 检查马腿是否被阻挡
    const horseLegs = this.getHorseLegs(position);
    const isBlocked = horseLegs.some(legPos => 
      existingUnits.some(unit => 
        unit.position.x === legPos.x && unit.position.y === legPos.y
      )
    );

    if (isBlocked) {
      return { canDeploy: false, reason: '马腿被阻挡，无法部署' };
    }

    return { canDeploy: true };
  }

  // 战车（车）部署规则：需要直线通道
  private static validateChariotPlacement(position: Position): { canDeploy: boolean; reason?: string } {
    if (!this.isInOwnTerritory(position)) {
      return { canDeploy: false, reason: '战车只能部署在己方区域' };
    }
    return { canDeploy: true };
  }

  // 谋士（士）部署规则：只能在九宫格内
  private static validateAdvisorPlacement(position: Position): { canDeploy: boolean; reason?: string } {
    if (!this.isInPalace(position)) {
      return { canDeploy: false, reason: '谋士只能部署在九宫格内' };
    }
    return { canDeploy: true };
  }

  // 丞相（象）部署规则：象飞田字，不能过河
  private static validateMinisterPlacement(
    position: Position,
    existingUnits: ChessUnit[]
  ): { canDeploy: boolean; reason?: string } {
    if (!this.isInOwnTerritory(position)) {
      return { canDeploy: false, reason: '丞相不能过河，只能在己方区域' };
    }

    // 检查是否在田字格的合法位置
    const validFieldPositions = this.getValidFieldPositions();
    const isValidField = validFieldPositions.some(
      pos => pos.x === position.x && pos.y === position.y
    );

    if (!isValidField) {
      return { canDeploy: false, reason: '丞相只能部署在田字格中心位置' };
    }

    // 检查象眼是否被阻挡
    const elephantEyes = this.getElephantEyes(position);
    const isBlocked = elephantEyes.some(eyePos => 
      existingUnits.some(unit => 
        unit.position.x === eyePos.x && unit.position.y === eyePos.y
      )
    );

    if (isBlocked) {
      return { canDeploy: false, reason: '象眼被阻挡，无法部署' };
    }

    return { canDeploy: true };
  }

  // 元帅（将）部署规则：只能在九宫格内，且每方只能有一个
  private static validateGeneralPlacement(position: Position): { canDeploy: boolean; reason?: string } {
    if (!this.isInPalace(position)) {
      return { canDeploy: false, reason: '元帅只能部署在九宫格内' };
    }
    return { canDeploy: true };
  }

  // 获取马腿位置（马走日字的阻挡点）
  private static getHorseLegs(position: Position): Position[] {
    const legs: Position[] = [];
    
    // 马走日字的8个方向，每个方向的马腿位置
    const directions = [
      { dx: 0, dy: -1 }, // 上
      { dx: 0, dy: 1 },  // 下
      { dx: -1, dy: 0 }, // 左
      { dx: 1, dy: 0 }   // 右
    ];

    directions.forEach(dir => {
      const legPos = {
        x: position.x + dir.dx,
        y: position.y + dir.dy
      };
      if (this.isValidPosition(legPos)) {
        legs.push(legPos);
      }
    });

    return legs;
  }

  // 获取象眼位置（象飞田字的阻挡点）
  private static getElephantEyes(position: Position): Position[] {
    const eyes: Position[] = [];
    
    // 象飞田字的4个对角方向的象眼位置
    const directions = [
      { dx: -1, dy: -1 }, // 左上
      { dx: 1, dy: -1 },  // 右上
      { dx: -1, dy: 1 },  // 左下
      { dx: 1, dy: 1 }    // 右下
    ];

    directions.forEach(dir => {
      const eyePos = {
        x: position.x + dir.dx,
        y: position.y + dir.dy
      };
      if (this.isValidPosition(eyePos)) {
        eyes.push(eyePos);
      }
    });

    return eyes;
  }

  // 获取田字格的合法位置
  private static getValidFieldPositions(): Position[] {
    return [
      { x: 2, y: 7 }, { x: 6, y: 7 }, // 第7行
      { x: 2, y: 5 }, { x: 6, y: 5 }  // 第5行
    ];
  }

  // 检查炮架是否可用
  private static checkCannonMountAvailable(
    position: Position,
    existingUnits: ChessUnit[]
  ): boolean {
    // 检查前方是否有单位可作为炮架
    for (let y = position.y - 1; y >= 0; y--) {
      const hasUnit = existingUnits.some(
        unit => unit.position.x === position.x && unit.position.y === y
      );
      if (hasUnit) {
        return true;
      }
    }
    return false;
  }

  // 获取单位的有效攻击位置（考虑象棋规则）
  static getValidAttackPositions(
    unit: ChessUnit,
    existingUnits: ChessUnit[],
    boardLayout: number[][]
  ): Position[] {
    const positions: Position[] = [];
    const { position, type } = unit;

    switch (type) {
      case 'soldier':
        // 兵只能向前攻击，过河后可以横向攻击
        positions.push({ x: position.x, y: position.y - 1 });
        if (position.y < 5) { // 过河后
          positions.push({ x: position.x - 1, y: position.y });
          positions.push({ x: position.x + 1, y: position.y });
        }
        break;

      case 'cannon':
        // 炮需要隔子攻击
        positions.push(...this.getCannonAttackPositions(position, existingUnits));
        break;

      case 'horse':
        // 马走日字
        positions.push(...this.getHorseAttackPositions(position, existingUnits));
        break;

      case 'chariot':
        // 车直线攻击
        positions.push(...this.getChariotAttackPositions(position, existingUnits));
        break;

      case 'advisor':
        // 士斜向攻击，限制在九宫格内
        positions.push(...this.getAdvisorAttackPositions(position));
        break;

      case 'minister':
        // 象田字攻击
        positions.push(...this.getMinisterAttackPositions(position, existingUnits));
        break;

      case 'general':
        // 将直线攻击，限制在九宫格内
        positions.push(...this.getGeneralAttackPositions(position));
        break;
    }

    // 过滤掉无效位置
    return positions.filter(pos => 
      this.isValidPosition(pos) && 
      boardLayout[pos.y] && 
      boardLayout[pos.y][pos.x] === 1
    );
  }

  // 获取炮的攻击位置（隔子攻击）
  private static getCannonAttackPositions(
    position: Position,
    existingUnits: ChessUnit[]
  ): Position[] {
    const positions: Position[] = [];
    const directions = [
      { dx: 0, dy: -1 }, // 上
      { dx: 0, dy: 1 },  // 下
      { dx: -1, dy: 0 }, // 左
      { dx: 1, dy: 0 }   // 右
    ];

    directions.forEach(dir => {
      let foundMount = false;
      for (let i = 1; i < 10; i++) {
        const checkPos = {
          x: position.x + dir.dx * i,
          y: position.y + dir.dy * i
        };

        if (!this.isValidPosition(checkPos)) break;

        const hasUnit = existingUnits.some(
          unit => unit.position.x === checkPos.x && unit.position.y === checkPos.y
        );

        if (hasUnit && !foundMount) {
          foundMount = true; // 找到炮架
        } else if (hasUnit && foundMount) {
          positions.push(checkPos); // 找到目标
          break;
        }
      }
    });

    return positions;
  }

  // 获取马的攻击位置（日字攻击）
  private static getHorseAttackPositions(
    position: Position,
    existingUnits: ChessUnit[]
  ): Position[] {
    const positions: Position[] = [];
    const moves = [
      { dx: -2, dy: -1, legX: -1, legY: 0 },
      { dx: -2, dy: 1, legX: -1, legY: 0 },
      { dx: 2, dy: -1, legX: 1, legY: 0 },
      { dx: 2, dy: 1, legX: 1, legY: 0 },
      { dx: -1, dy: -2, legX: 0, legY: -1 },
      { dx: 1, dy: -2, legX: 0, legY: -1 },
      { dx: -1, dy: 2, legX: 0, legY: 1 },
      { dx: 1, dy: 2, legX: 0, legY: 1 }
    ];

    moves.forEach(move => {
      const targetPos = {
        x: position.x + move.dx,
        y: position.y + move.dy
      };
      const legPos = {
        x: position.x + move.legX,
        y: position.y + move.legY
      };

      // 检查马腿是否被阻挡
      const isLegBlocked = existingUnits.some(
        unit => unit.position.x === legPos.x && unit.position.y === legPos.y
      );

      if (!isLegBlocked && this.isValidPosition(targetPos)) {
        positions.push(targetPos);
      }
    });

    return positions;
  }

  // 获取车的攻击位置（直线攻击）
  private static getChariotAttackPositions(
    position: Position,
    existingUnits: ChessUnit[]
  ): Position[] {
    const positions: Position[] = [];
    const directions = [
      { dx: 0, dy: -1 }, // 上
      { dx: 0, dy: 1 },  // 下
      { dx: -1, dy: 0 }, // 左
      { dx: 1, dy: 0 }   // 右
    ];

    directions.forEach(dir => {
      for (let i = 1; i < 10; i++) {
        const targetPos = {
          x: position.x + dir.dx * i,
          y: position.y + dir.dy * i
        };

        if (!this.isValidPosition(targetPos)) break;

        positions.push(targetPos);

        // 如果遇到单位则停止
        const hasUnit = existingUnits.some(
          unit => unit.position.x === targetPos.x && unit.position.y === targetPos.y
        );
        if (hasUnit) break;
      }
    });

    return positions;
  }

  // 获取士的攻击位置
  private static getAdvisorAttackPositions(position: Position): Position[] {
    const positions: Position[] = [];
    const moves = [
      { dx: -1, dy: -1 },
      { dx: 1, dy: -1 },
      { dx: -1, dy: 1 },
      { dx: 1, dy: 1 }
    ];

    moves.forEach(move => {
      const targetPos = {
        x: position.x + move.dx,
        y: position.y + move.dy
      };

      if (this.isInPalace(targetPos)) {
        positions.push(targetPos);
      }
    });

    return positions;
  }

  // 获取象的攻击位置
  private static getMinisterAttackPositions(
    position: Position,
    existingUnits: ChessUnit[]
  ): Position[] {
    const positions: Position[] = [];
    const moves = [
      { dx: -2, dy: -2, eyeX: -1, eyeY: -1 },
      { dx: 2, dy: -2, eyeX: 1, eyeY: -1 },
      { dx: -2, dy: 2, eyeX: -1, eyeY: 1 },
      { dx: 2, dy: 2, eyeX: 1, eyeY: 1 }
    ];

    moves.forEach(move => {
      const targetPos = {
        x: position.x + move.dx,
        y: position.y + move.dy
      };
      const eyePos = {
        x: position.x + move.eyeX,
        y: position.y + move.eyeY
      };

      // 检查象眼是否被阻挡
      const isEyeBlocked = existingUnits.some(
        unit => unit.position.x === eyePos.x && unit.position.y === eyePos.y
      );

      if (!isEyeBlocked && this.isInOwnTerritory(targetPos)) {
        positions.push(targetPos);
      }
    });

    return positions;
  }

  // 获取将的攻击位置
  private static getGeneralAttackPositions(position: Position): Position[] {
    const positions: Position[] = [];
    const moves = [
      { dx: 0, dy: -1 },
      { dx: 0, dy: 1 },
      { dx: -1, dy: 0 },
      { dx: 1, dy: 0 }
    ];

    moves.forEach(move => {
      const targetPos = {
        x: position.x + move.dx,
        y: position.y + move.dy
      };

      if (this.isInPalace(targetPos)) {
        positions.push(targetPos);
      }
    });

    return positions;
  }
}